package me.youline.dataServer.service;

import java.util.List;

import javax.transaction.Transactional;

import me.youline.dataServer.dao.UserBaseInfoDAO;
import me.youline.dataServer.dao.UserSocialInfoRecorderDAO;
import me.youline.dataServer.dao.UserSocialRelationDAO;
import me.youline.dataServer.entity.UserRelationRecorder;
import me.youline.dataServer.entity.UserSocialRelation;
import me.youline.dataServer.exception.ReplicatedDataException;
import me.youline.dataServer.exception.UnExistDataException;
import me.youline.dataServer.service.socialAction.SocialActionEventPublisher;
import me.youline.dataServer.service.socialAction.event.FollowingSocialActionCancelEvent;
import me.youline.dataServer.service.socialAction.event.FollowingSocialActionExeEvent;
import me.youline.dataServer.utils.IdPagination;

import org.perf4j.aop.Profiled;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 社交关系操作业务类
 * 
 * @author linhan
 *
 */
@Service
public class SocialRelationService {

	@Autowired
	private UserSocialRelationDAO userSocialRelationDAO;

	@Autowired
	private UserSocialInfoRecorderDAO socialInfoDAO;

	@Autowired
	private UserBaseInfoDAO userBaseInfoDAO;
	
	@Autowired
	private SocialActionEventPublisher publisher;
	

	/**
	 * 创建社交关系，即fromUser 关注 touser，此方法调用会改变关注数、粉丝数
	 * 
	 * @param fromUserId
	 * @param toUserId
	 * @throws ReplicatedDataException
	 * @throws UnExistDataException
	 */
	@Transactional
	@Profiled(tag = "service-创建社交关系")
	public void buildSocialRelation(Long fromUserId, Long toUserId)
			throws ReplicatedDataException, UnExistDataException {
		checkUserExist(toUserId);
		if (userSocialRelationDAO.isFollowerToTargetUser(fromUserId, toUserId)) {
			throw new ReplicatedDataException("[ERROR][socialRelation service]{info:\"relation exists\", detail:{ " + fromUserId
					+ " -> " + toUserId+" }");
		}
		userSocialRelationDAO.addUserRelation(fromUserId, toUserId);
		socialInfoDAO.addFollowersNum(toUserId, 1);
		socialInfoDAO.addFollowingNum(fromUserId, 1);
		publisher.publishSocialEvent(new FollowingSocialActionExeEvent(fromUserId, toUserId));
	}

	/**
	 * 取消关注关系，即fromUserId用户取消对touserId的关注。
	 * 
	 * @param fromUserId
	 *            关注人
	 * @param toUserId
	 *            被关注者
	 */
	@Transactional
	@Profiled(tag = "service-取消社交关系")
	public void cancelFollowingRelation(Long fromUserId, Long toUserId) {
		if (userSocialRelationDAO.deleteUserRelation(fromUserId, toUserId)) {//成功删除关注记录后再减少统计数据
			socialInfoDAO.addFollowersNum(toUserId, -1);
			socialInfoDAO.addFollowingNum(fromUserId, -1);
			publisher.publishSocialEvent(new FollowingSocialActionCancelEvent(fromUserId, toUserId));
		}
	}

	/**
	 * 获取粉丝列表关系数据
	 * @param userId
	 * @param page
	 * @return
	 */
	@Profiled(tag = "service-获取粉丝列表关系数据")
	public List<UserSocialRelation> doGetUserFollowingRelation(Long userId,
			IdPagination page) {
		return userSocialRelationDAO.getUserFollowingRels(userId, page);
	}

	/**
	 * 获取关注列表关系数据
	 * 
	 * @param userId
	 * @param page
	 * @return
	 */
	@Profiled(tag = "service-获取关注列表关系数据")
	public List<UserSocialRelation> doGetUserFollowerRelation(Long userId,
			IdPagination page) {
		return userSocialRelationDAO.getFollowersByUserRels(userId, page);
	}

	/**
	 * 获取指定用户的粉丝数
	 * 
	 * @param targetUserId
	 * @return
	 */
	@Profiled(tag = "service-获取指定用户的粉丝数")
	public int getFollowerTotal(Long targetUserId) {
		UserRelationRecorder r = socialInfoDAO
				.getRelationTotalByUser(targetUserId);
		if (r == null) {
			return 0;
		}
		return r.getFollowersTotal();
	}
	
	/**
	 * 获取指定用户社交关系统计数据，可以一次性读取出粉丝数和关注人数，避免多次查询
	 * @param userId
	 * @return
	 */
	public UserRelationRecorder getSocialTotalRecorder(Long userId){
		return socialInfoDAO.getRelationTotalByUser(userId);
	}

	/**
	 * 确定查询用户是否被目标用户关注
	 * 
	 * @param queryUserId
	 * @param targetUserId
	 * @return
	 */
	@Profiled(tag = "service-查询用户是否被目标用户关注")
	public boolean isFollowed(Long queryUserId, Long targetUserId) {
		return userSocialRelationDAO.isFollowerToTargetUser(targetUserId,
				queryUserId);
	}

	/**
	 * 确定查询用户是否关注了目标用户
	 * 
	 * @param queryUserId
	 * @param targetUserId
	 * @return
	 */
	@Profiled(tag = "service-查询用户是否关注了目标用户")
	public boolean isFollowing(Long queryUserId, Long targetUserId) {
		return userSocialRelationDAO.isFollowerToTargetUser(queryUserId,
				targetUserId);
	}
	

	/**
	 * 获取推荐用户列表
	 * 
	 * @return
	 */
	@Profiled(tag = "service-获取推荐用户列表信息")
	public List<Long> getRecommendUserList() {
		return socialInfoDAO.getRecommendUserIds();
	}

	/**
	 * 获取指定用户的关注人总数
	 * 
	 * @param targetUserId
	 * @return
	 */
	@Profiled(tag = "service-查询用户关注人数")
	public int getFollowingTotal(Long targetUserId) {
		UserRelationRecorder r = socialInfoDAO
				.getRelationTotalByUser(targetUserId);
		if (r == null) {
			return 0;
		}
		return r.getFollowingTotal();
	}

	/**
	 * 确认当前用户是否存在
	 * 
	 * @param userId
	 * @throws UnExistDataException
	 */
	protected void checkUserExist(Long userId) throws UnExistDataException {
		if (!userBaseInfoDAO.exists(userId)) {
			throw new UnExistDataException("用户不存在");
		}
	}

}
